<template>
  <div class="min-h-screen bg-gradient-to-br from-blue-50 to-purple-50 py-8">
    <div class="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8">
      <div class="text-center mb-6">
        <h1 class="text-3xl font-bold">2048</h1>
        <p class="text-sm text-gray-600">使用方向键移动合并方块，目标合并到 2048。</p>
      </div>

      <div class="bg-white rounded-lg shadow p-4">
        <div class="flex items-center justify-between mb-3">
          <div>得分: <span class="font-medium">{{ score }}</span></div>
          <div>
            <button class="px-3 py-1 bg-blue-600 text-white rounded" @click="reset">重置</button>
          </div>
        </div>

        <div class="grid gap-2" style="grid-template-columns: repeat(4, 1fr)">
          <div v-for="(cell, idx) in flatBoard" :key="idx" class="h-20 rounded flex items-center justify-center text-xl font-bold"
            :class="tileClass(cell)">
            <span v-if="cell">{{ cell }}</span>
          </div>
        </div>

        <div class="mt-3 text-sm text-gray-500">使用 ← ↑ → ↓ 控制。达到 2048 则显示成功。</div>
        <div v-if="won" class="mt-3 p-3 bg-green-50 rounded">恭喜！已达 2048</div>
        <div v-if="gameover" class="mt-3 p-3 bg-red-50 rounded">游戏结束，没有可移动的格子</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'

const SIZE = 4
const board = ref(Array(SIZE).fill(null).map(()=>Array(SIZE).fill(0)))
const score = ref(0)
const won = ref(false)
const gameover = ref(false)

function reset(){
  for(let r=0;r<SIZE;r++) for(let c=0;c<SIZE;c++) board.value[r][c]=0
  score.value = 0
  won.value = false
  gameover.value = false
  addRandom(); addRandom()
}

function addRandom(){
  const empties = []
  for(let r=0;r<SIZE;r++) for(let c=0;c<SIZE;c++) if(board.value[r][c]===0) empties.push([r,c])
  if(!empties.length) return
  const [r,c] = empties[Math.floor(Math.random()*empties.length)]
  board.value[r][c] = Math.random() < 0.9 ? 2 : 4
}

function transpose(m){
  const res = Array(SIZE).fill(null).map(()=>Array(SIZE).fill(0))
  for(let r=0;r<SIZE;r++) for(let c=0;c<SIZE;c++) res[r][c] = m[c][r]
  return res
}

function reverseRows(m){
  return m.map(row => row.slice().reverse())
}

function moveLeft(){
  let moved=false
  for(let r=0;r<SIZE;r++){
    const row = board.value[r].filter(v=>v!==0)
    for(let i=0;i<row.length-1;i++){
      if(row[i]===row[i+1]){ row[i]*=2; score.value += row[i]; row.splice(i+1,1); if(row[i]===2048) won.value = true }
    }
    while(row.length<SIZE) row.push(0)
    for(let c=0;c<SIZE;c++){
      if(board.value[r][c] !== row[c]) moved = true
      board.value[r][c] = row[c]
    }
  }
  return moved
}

function moveRight(){
  board.value = reverseRows(board.value)
  const moved = moveLeft()
  board.value = reverseRows(board.value)
  return moved
}

function moveUp(){
  board.value = transpose(board.value)
  const moved = moveLeft()
  board.value = transpose(board.value)
  return moved
}

function moveDown(){
  board.value = transpose(board.value)
  board.value = reverseRows(board.value)
  const moved = moveLeft()
  board.value = reverseRows(board.value)
  board.value = transpose(board.value)
  return moved
}

function canMove(){
  // check empty
  for(let r=0;r<SIZE;r++) for(let c=0;c<SIZE;c++) if(board.value[r][c]===0) return true
  // check merges
  for(let r=0;r<SIZE;r++) for(let c=0;c<SIZE-1;c++) if(board.value[r][c]===board.value[r][c+1]) return true
  for(let c=0;c<SIZE;c++) for(let r=0;r<SIZE-1;r++) if(board.value[r][c]===board.value[r+1][c]) return true
  return false
}

function handleMove(dir){
  if (won.value || gameover.value) return
  let moved=false
  if(dir==='left') moved = moveLeft()
  if(dir==='right') moved = moveRight()
  if(dir==='up') moved = moveUp()
  if(dir==='down') moved = moveDown()
  if (moved) { addRandom(); if(!canMove()) gameover.value = true }
}

function onKey(e){
  if(e.key === 'ArrowLeft') handleMove('left')
  if(e.key === 'ArrowRight') handleMove('right')
  if(e.key === 'ArrowUp') handleMove('up')
  if(e.key === 'ArrowDown') handleMove('down')
}

onMounted(()=>{ reset(); window.addEventListener('keydown', onKey) })
onBeforeUnmount(()=>{ window.removeEventListener('keydown', onKey) })

const flatBoard = computed(()=> board.value.flat())

function tileClass(v){
  if(!v) return 'bg-gray-100 text-gray-400'
  if(v===2) return 'bg-yellow-100'
  if(v===4) return 'bg-yellow-200'
  if(v===8) return 'bg-orange-200 text-white'
  if(v===16) return 'bg-orange-300 text-white'
  if(v>=32) return 'bg-red-400 text-white'
  return 'bg-gray-200'
}
</script>

<style scoped>
</style>
